import os
import numpy as np
import pandas as pd
from math import floor, ceil
from bisect import bisect_left, bisect_right
import plotly.express as px
import plotly.graph_objects as go
# Get data path
data_path = f"{os.path.dirname(os.getcwd())}/data"
print(data_path)
/Users/shawnguyen/Desktop/national-exam-scores-visuals/ds/data
# Read grades
grades = {}
for year in range(2018, 2022):
grades[year] = pd.read_csv(f'{data_path}/diemthi{year}.csv')
grades[year] = grades[year][["ID", "CityCode", "CityArea", "Math", "Literature", "English", "Physics", "Chemistry", "Biology", "Geography", "History", "Civic Education"]]
display(grades[2021])
| ID | CityCode | CityArea | Math | Literature | English | Physics | Chemistry | Biology | Geography | History | Civic Education | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1000001 | 1 | 1.0 | 2.2 | 3.50 | NaN | NaN | NaN | NaN | 5.50 | 2.50 | NaN |
| 1 | 1000002 | 1 | 1.0 | 9.2 | 8.25 | 10.0 | NaN | NaN | NaN | 9.75 | 5.75 | 9.25 |
| 2 | 1000003 | 1 | 1.0 | 4.4 | 6.25 | NaN | NaN | NaN | NaN | 4.00 | 4.25 | NaN |
| 3 | 1000004 | 1 | 1.0 | 8.4 | 6.75 | 10.0 | 4.00 | 3.00 | 3.50 | NaN | NaN | NaN |
| 4 | 1000005 | 1 | 1.0 | 8.8 | 8.25 | 9.4 | 8.25 | 5.75 | 5.25 | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 1002265 | 64006834 | 64 | 6.0 | 8.6 | 8.25 | 6.2 | 8.25 | 7.00 | 6.50 | NaN | NaN | NaN |
| 1002266 | 64006835 | 64 | 6.0 | 9.0 | 7.50 | 9.4 | 8.00 | 8.25 | 5.50 | NaN | NaN | NaN |
| 1002267 | 64006836 | 64 | 6.0 | 4.8 | 7.00 | 4.6 | NaN | NaN | NaN | 7.00 | 3.75 | 9.00 |
| 1002268 | 64006837 | 64 | 6.0 | 7.4 | 7.75 | 9.4 | NaN | NaN | NaN | 6.75 | 4.50 | 9.25 |
| 1002269 | 64006838 | 64 | 6.0 | 8.0 | 7.75 | 8.2 | NaN | NaN | NaN | 6.50 | 4.25 | 7.50 |
1002270 rows × 12 columns
# Declare subjects combination
sbs = {}
sbs['A00'] = ["Math", "Physics", "Chemistry"]
sbs['A01'] = ["Math", "Physics", "English"]
sbs['A02'] = ["Math", "Physics", "Biology"]
sbs['A03'] = ["Math", "Physics", "History"]
sbs['A04'] = ["Math", "Physics", "Geography"]
sbs['A05'] = ["Math", "Chemistry", "History"]
sbs['A06'] = ["Math", "Chemistry", "Geography"]
sbs['A07'] = ["Math", "History", "Geography"]
sbs['A08'] = ["Math", "History", "Civic Education"]
sbs['A09'] = ["Math", "Geography", "Civic Education"]
sbs['A10'] = ["Math", "Physics", "Civic Education"]
sbs['A11'] = ["Math", "Chemistry", "Civic Education"]
sbs['B00'] = ["Math", "Chemistry", "Biology"]
sbs['B01'] = ["Math", "Biology", "History"]
sbs['B02'] = ["Math", "Biology", "Geography"]
sbs['B03'] = ["Math", "Biology", "Literature"]
sbs['B04'] = ["Math", "Biology", "Civic Education"]
sbs['B08'] = ["Math", "Biology", "English"]
sbs['C00'] = ["Literature", "History", "Geography"]
sbs['C01'] = ["Literature", "Math", "Physics"]
sbs['C02'] = ["Literature", "Math", "Chemistry"]
sbs['C03'] = ["Literature", "Math", "History"]
sbs['C04'] = ["Literature", "Math", "Geography"]
sbs['C05'] = ["Literature", "Physics", "Chemistry"]
sbs['C06'] = ["Literature", "Physics", "Biology"]
sbs['C07'] = ["Literature", "Physics", "History"]
sbs['C08'] = ["Literature", "Chemistry", "Biology"]
sbs['C09'] = ["Literature", "Physics", "Geography"]
sbs['C10'] = ["Literature", "Chemistry", "History"]
sbs['C12'] = ["Literature", "Biology", "History"]
sbs['C13'] = ["Literature", "Biology", "Geography"]
sbs['C14'] = ["Literature", "Math", "Civic Education"]
sbs['C16'] = ["Literature", "Physics", "Civic Education"]
sbs['C17'] = ["Literature", "Chemistry", "Civic Education"]
sbs['C19'] = ["Literature", "History", "Civic Education"]
sbs['C20'] = ["Literature", "Geography", "Civic Education"]
sbs['D01'] = ["Literature", "Math", "English"]
sbs['D07'] = ["Math", "Chemistry", "English"]
sbs['D08'] = ["Math", "Biology", "English"]
sbs['D09'] = ["Math", "History", "English"]
sbs['D10'] = ["Math", "Geography", "English"]
sbs['D11'] = ["Literature", "Physics", "English"]
sbs['D12'] = ["Literature", "Chemistry", "English"]
sbs['D13'] = ["Literature", "Biology", "English"]
sbs['D14'] = ["Literature", "History", "English"]
sbs['D15'] = ["Literature", "Geography", "English"]
sbs['D66'] = ["Literature", "Civic Education", "English"]
sbs['D84'] = ["Math", "Civic Education", "English"]
sbs['A00-Math'] = ["Math", "Physics", "Chemistry", "Math"]
sbs['A01-Math'] = ["Math", "Physics", "English", "Math"]
sbs['A02-Math'] = ["Math", "Physics", "Biology", "Math"]
sbs['A03-Math'] = ["Math", "Physics", "History", "Math"]
sbs['A04-Math'] = ["Math", "Physics", "Geography", "Math"]
sbs['A05-Math'] = ["Math", "Chemistry", "History", "Math"]
sbs['A06-Math'] = ["Math", "Chemistry", "Geography", "Math"]
sbs['A07-Math'] = ["Math", "History", "Geography", "Math"]
sbs['A08-Math'] = ["Math", "History", "Civic Education", "Math"]
sbs['A09-Math'] = ["Math", "Geography", "Civic Education", "Math"]
sbs['A10-Math'] = ["Math", "Physics", "Civic Education", "Math"]
sbs['A11-Math'] = ["Math", "Chemistry", "Civic Education", "Math"]
sbs['B00-Math'] = ["Math", "Chemistry", "Biology", "Math"]
sbs['B01-Math'] = ["Math", "Biology", "History", "Math"]
sbs['B02-Math'] = ["Math", "Biology", "Geography", "Math"]
sbs['B03-Math'] = ["Math", "Biology", "Literature", "Math"]
sbs['B04-Math'] = ["Math", "Biology", "Civic Education", "Math"]
sbs['B08-Math'] = ["Math", "Biology", "English", "Math"]
sbs['C00-Math'] = ["Literature", "History", "Geography", "Math"]
sbs['C01-Math'] = ["Literature", "Math", "Physics", "Math"]
sbs['C02-Math'] = ["Literature", "Math", "Chemistry", "Math"]
sbs['C03-Math'] = ["Literature", "Math", "History", "Math"]
sbs['C04-Math'] = ["Literature", "Math", "Geography", "Math"]
sbs['C05-Math'] = ["Literature", "Physics", "Chemistry", "Math"]
sbs['C06-Math'] = ["Literature", "Physics", "Biology", "Math"]
sbs['C07-Math'] = ["Literature", "Physics", "History", "Math"]
sbs['C08-Math'] = ["Literature", "Chemistry", "Biology", "Math"]
sbs['C09-Math'] = ["Literature", "Physics", "Geography", "Math"]
sbs['C10-Math'] = ["Literature", "Chemistry", "History", "Math"]
sbs['C12-Math'] = ["Literature", "Biology", "History", "Math"]
sbs['C13-Math'] = ["Literature", "Biology", "Geography", "Math"]
sbs['C14-Math'] = ["Literature", "Math", "Civic Education", "Math"]
sbs['C16-Math'] = ["Literature", "Physics", "Civic Education", "Math"]
sbs['C17-Math'] = ["Literature", "Chemistry", "Civic Education", "Math"]
sbs['C19-Math'] = ["Literature", "History", "Civic Education", "Math"]
sbs['C20-Math'] = ["Literature", "Geography", "Civic Education", "Math"]
sbs['D01-Math'] = ["Literature", "Math", "English", "Math"]
sbs['D07-Math'] = ["Math", "Chemistry", "English", "Math"]
sbs['D08-Math'] = ["Math", "Biology", "English", "Math"]
sbs['D09-Math'] = ["Math", "History", "English", "Math"]
sbs['D10-Math'] = ["Math", "Geography", "English", "Math"]
sbs['D11-Math'] = ["Literature", "Physics", "English", "Math"]
sbs['D12-Math'] = ["Literature", "Chemistry", "English", "Math"]
sbs['D13-Math'] = ["Literature", "Biology", "English", "Math"]
sbs['D14-Math'] = ["Literature", "History", "English", "Math"]
sbs['D15-Math'] = ["Literature", "Geography", "English", "Math"]
sbs['D66-Math'] = ["Literature", "Civic Education", "English", "Math"]
sbs['D84-Math'] = ["Math", "Civic Education", "English", "Math"]
sbs['A00-English'] = ["Math", "Physics", "Chemistry", "English"]
sbs['A01-English'] = ["Math", "Physics", "English", "English"]
sbs['A02-English'] = ["Math", "Physics", "Biology", "English"]
sbs['A03-English'] = ["Math", "Physics", "History", "English"]
sbs['A04-English'] = ["Math", "Physics", "Geography", "English"]
sbs['A05-English'] = ["Math", "Chemistry", "History", "English"]
sbs['A06-English'] = ["Math", "Chemistry", "Geography", "English"]
sbs['A07-English'] = ["Math", "History", "Geography", "English"]
sbs['A08-English'] = ["Math", "History", "Civic Education", "English"]
sbs['A09-English'] = ["Math", "Geography", "Civic Education", "English"]
sbs['A10-English'] = ["Math", "Physics", "Civic Education", "English"]
sbs['A11-English'] = ["Math", "Chemistry", "Civic Education", "English"]
sbs['B00-English'] = ["Math", "Chemistry", "Biology", "English"]
sbs['B01-English'] = ["Math", "Biology", "History", "English"]
sbs['B02-English'] = ["Math", "Biology", "Geography", "English"]
sbs['B03-English'] = ["Math", "Biology", "Literature", "English"]
sbs['B04-English'] = ["Math", "Biology", "Civic Education", "English"]
sbs['B08-English'] = ["Math", "Biology", "English", "English"]
sbs['C00-English'] = ["Literature", "History", "Geography", "English"]
sbs['C01-English'] = ["Literature", "Math", "Physics", "English"]
sbs['C02-English'] = ["Literature", "Math", "Chemistry", "English"]
sbs['C03-English'] = ["Literature", "Math", "History", "English"]
sbs['C04-English'] = ["Literature", "Math", "Geography", "English"]
sbs['C05-English'] = ["Literature", "Physics", "Chemistry", "English"]
sbs['C06-English'] = ["Literature", "Physics", "Biology", "English"]
sbs['C07-English'] = ["Literature", "Physics", "History", "English"]
sbs['C08-English'] = ["Literature", "Chemistry", "Biology", "English"]
sbs['C09-English'] = ["Literature", "Physics", "Geography", "English"]
sbs['C10-English'] = ["Literature", "Chemistry", "History", "English"]
sbs['C12-English'] = ["Literature", "Biology", "History", "English"]
sbs['C13-English'] = ["Literature", "Biology", "Geography", "English"]
sbs['C14-English'] = ["Literature", "Math", "Civic Education", "English"]
sbs['C16-English'] = ["Literature", "Physics", "Civic Education", "English"]
sbs['C17-English'] = ["Literature", "Chemistry", "Civic Education", "English"]
sbs['C19-English'] = ["Literature", "History", "Civic Education", "English"]
sbs['C20-English'] = ["Literature", "Geography", "Civic Education", "English"]
sbs['D01-English'] = ["Literature", "Math", "English", "English"]
sbs['D07-English'] = ["Math", "Chemistry", "English", "English"]
sbs['D08-English'] = ["Math", "Biology", "English", "English"]
sbs['D09-English'] = ["Math", "History", "English", "English"]
sbs['D10-English'] = ["Math", "Geography", "English", "English"]
sbs['D11-English'] = ["Literature", "Physics", "English", "English"]
sbs['D12-English'] = ["Literature", "Chemistry", "English", "English"]
sbs['D13-English'] = ["Literature", "Biology", "English", "English"]
sbs['D14-English'] = ["Literature", "History", "English", "English"]
sbs['D15-English'] = ["Literature", "Geography", "English", "English"]
sbs['D66-English'] = ["Literature", "Civic Education", "English", "English"]
sbs['D84-English'] = ["Math", "Civic Education", "English", "English"]
len(sbs)
144
# Compute grades for each subjects combination
for year in grades:
for sb in sbs:
grades[year][sb] = 0
for x in sbs[sb]:
grades[year][sb] = grades[year][sb] + grades[year][x]
grades[year][sb] *= 3/len(sbs[sb]) # Normalizing
display(grades[2021])
/var/folders/ln/rz3xh60x0zbb7cfm8z1lrlm40000gn/T/ipykernel_81835/148978670.py:4: PerformanceWarning: DataFrame is highly fragmented. This is usually the result of calling `frame.insert` many times, which has poor performance. Consider joining all columns at once using pd.concat(axis=1) instead. To get a de-fragmented frame, use `newframe = frame.copy()` grades[year][sb] = 0
| ID | CityCode | CityArea | Math | Literature | English | Physics | Chemistry | Biology | Geography | ... | D08-English | D09-English | D10-English | D11-English | D12-English | D13-English | D14-English | D15-English | D66-English | D84-English | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| 0 | 1000001 | 1 | 1.0 | 2.2 | 3.50 | NaN | NaN | NaN | NaN | 5.50 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 1 | 1000002 | 1 | 1.0 | 9.2 | 8.25 | 10.0 | NaN | NaN | NaN | 9.75 | ... | NaN | 26.2125 | 29.2125 | NaN | NaN | NaN | 25.5000 | 28.5000 | 28.1250 | 28.8375 |
| 2 | 1000003 | 1 | 1.0 | 4.4 | 6.25 | NaN | NaN | NaN | NaN | 4.00 | ... | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN | NaN |
| 3 | 1000004 | 1 | 1.0 | 8.4 | 6.75 | 10.0 | 4.00 | 3.00 | 3.50 | NaN | ... | 23.9250 | NaN | NaN | 23.0625 | 22.3125 | 22.6875 | NaN | NaN | NaN | NaN |
| 4 | 1000005 | 1 | 1.0 | 8.8 | 8.25 | 9.4 | 8.25 | 5.75 | 5.25 | NaN | ... | 24.6375 | NaN | NaN | 26.4750 | 24.6000 | 24.2250 | NaN | NaN | NaN | NaN |
| ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... | ... |
| 1002265 | 64006834 | 64 | 6.0 | 8.6 | 8.25 | 6.2 | 8.25 | 7.00 | 6.50 | NaN | ... | 20.6250 | NaN | NaN | 21.6750 | 20.7375 | 20.3625 | NaN | NaN | NaN | NaN |
| 1002266 | 64006835 | 64 | 6.0 | 9.0 | 7.50 | 9.4 | 8.00 | 8.25 | 5.50 | NaN | ... | 24.9750 | NaN | NaN | 25.7250 | 25.9125 | 23.8500 | NaN | NaN | NaN | NaN |
| 1002267 | 64006836 | 64 | 6.0 | 4.8 | 7.00 | 4.6 | NaN | NaN | NaN | 7.00 | ... | NaN | 13.3125 | 15.7500 | NaN | NaN | NaN | 14.9625 | 17.4000 | 18.9000 | 17.2500 |
| 1002268 | 64006837 | 64 | 6.0 | 7.4 | 7.75 | 9.4 | NaN | NaN | NaN | 6.75 | ... | NaN | 23.0250 | 24.7125 | NaN | NaN | NaN | 23.2875 | 24.9750 | 26.8500 | 26.5875 |
| 1002269 | 64006838 | 64 | 6.0 | 8.0 | 7.75 | 8.2 | NaN | NaN | NaN | 6.50 | ... | NaN | 21.4875 | 23.1750 | NaN | NaN | NaN | 21.3000 | 22.9875 | 23.7375 | 23.9250 |
1002270 rows × 156 columns
# Read standard grades
standard_grades = {}
for year in range(2018, 2022):
standard_grades[year] = pd.read_csv(f'{data_path}/standard_grades_{year}.csv')
standard_grades[year]['Main Subject'] = standard_grades[year]['Main Subject'].fillna("")
display(standard_grades[2021])
| Major ID | Major | Subjects Combination | Standard Grade | Main Subject | |
|---|---|---|---|---|---|
| 0 | BF1 | Kỹ thuật Sinh học | A00, B00 | 25.34 | Math |
| 1 | BF2 | Kỹ thuật Thực phẩm | A00, B00 | 25.94 | Math |
| 2 | CH1 | Kỹ thuật Hóa học | A00, B00, D07 | 25.20 | Math |
| 3 | CH2 | Hóa học | A00, B00, D07 | 24.96 | Math |
| 4 | CH3 | Kỹ thuật In | A00, B00, D07 | 24.45 | Math |
| 5 | ED2 | Công nghệ Giáo dục | A00, A01, D01 | 24.80 | |
| 6 | EE1 | Kỹ thuật Điện | A00, A01 | 26.50 | |
| 7 | EE2 | Kỹ thuật Điều khiển và Tự động hóa | A00, A01 | 27.46 | Math |
| 8 | EM1 | Kinh tế Công nghiệp | A00, A01, D01 | 25.65 | |
| 9 | EM2 | Quản lý Công nghiệp | A00, A01, D01 | 25.75 | |
| 10 | EM3 | Quản trị Kinh doanh | A00, A01, D01 | 26.04 | |
| 11 | EM4 | Kế toán | A00, A01, D01 | 25.76 | |
| 12 | EM5 | Tài chính Ngân hàng | A00, A01, D01 | 25.83 | |
| 13 | ET1 | Kỹ thuật Điện tử Viễn thông | A00, A01 | 26.80 | Math |
| 14 | EV1 | Kỹ thuật Môi trường | A00, B00, D07 | 24.01 | Math |
| 15 | EV2 | Quản lý Tài nguyên và Môi trường* | A00, B00, D07 | 23.53 | |
| 16 | FL1 | Tiếng Anh KHKT và Công nghệ | D01 | 26.39 | English |
| 17 | FL2 | Tiếng Anh chuyên nghiệp quốc tế | D01 | 26.11 | English |
| 18 | HE1 | Kỹ thuật Nhiệt | A00, A01 | 24.50 | Math |
| 19 | IT1 | Khoa học Máy tính | A00, A01 | 28.43 | Math |
| 20 | IT2 | Kỹ thuật Máy tính | A00, A01 | 28.10 | Math |
| 21 | ME1 | Kỹ thuật Cơ điện tử | A00, A01 | 26.91 | Math |
| 22 | ME2 | Kỹ thuật Cơ khí | A00, A01 | 25.78 | Math |
| 23 | MI1 | Toán Tin | A00, A01 | 27.00 | Math |
| 24 | MI2 | Hệ thống thông tin quản lý | A00, A01 | 27.00 | Math |
| 25 | MS1 | Kỹ thuật Vật liệu | A00, A01, D07 | 24.65 | Math |
| 26 | PH1 | Vật lý Kỹ thuật | A00, A01, A02 | 25.64 | Math |
| 27 | PH2 | Kỹ thuật Hạt nhân | A00, A01, A02 | 24.48 | Math |
| 28 | PH3 | Vật lý Y khoa* | A00, A01, A02 | 25.36 | |
| 29 | TE1 | Kỹ thuật Ô tô | A00, A01 | 26.94 | Math |
| 30 | TE2 | Kỹ thuật Cơ khí động lực | A00, A01 | 25.70 | Math |
| 31 | TE3 | Kỹ thuật Hàng không | A00, A01 | 26.48 | Math |
| 32 | TX1 | Kỹ thuật Dệt May | A00, A01 | 23.99 | Math |
| 33 | BF-E12 | Kỹ thuật Thực phẩm (Chương trình tiên tiến) | A00, B00 | 24.44 | Math |
| 34 | CH-E11 | Kỹ thuật Hóa dược (Chương trình tiên tiến) | A00, B00, D07 | 26.40 | Math |
| 35 | EE-E18 | Hệ thống điện và năng lượng tái tạo (Chương tr... | A00, A01 | 25.71 | |
| 36 | EE-E8 | Kỹ thuật điều khiển Tự động hóa (Chương trình ... | A00, A01 | 27.26 | Math |
| 37 | EE-EP | Tin học công nghiệp và Tự động hóa (Chương trì... | A00, A01, D29 | 26.14 | Math |
| 38 | EM-E13 | Phân tích Kinh doanh (Chương trình tiên tiến) | D07, A01, D01 | 25.55 | Math |
| 39 | EM-E14 | Logistics và Quản lý chuỗi cung ứng (Chương tr... | D07, A01, D01 | 26.33 | |
| 40 | ET-E4 | Kỹ thuật Điện tử Viễn thông (Chương trình tiên... | A00, A01 | 26.59 | Math |
| 41 | ET-E5 | Kỹ thuật Y sinh (Chương trình tiên tiến) | A00, A01 | 25.88 | Math |
| 42 | ET-E9 | Hệ thống nhúng thông minh và IoT (Chương trình... | A00, A01, D28 | 26.93 | Math |
| 43 | ET-E16 | Truyền thông số và Kỹ thuật đa phương tiện (Ch... | A00, A01 | 26.59 | |
| 44 | IT-E6 | Công nghệ Thông tin Việt-Nhật (Chương trình ti... | A00, A01, D28 | 27.40 | Math |
| 45 | IT-E7 | Công nghệ Thông tin Global ICT (Chương trình t... | A00, A01 | 27.85 | Math |
| 46 | IT-E10 | Khoa học Dữ liệu và Trí tuệ nhân tạo (Chương t... | A00, A01 | 28.04 | Math |
| 47 | IT-E15 | An toàn không gian số* (Chương trình tiên tiến) | A00, A01 | 27.44 | |
| 48 | IT-EP | Công nghệ Thông tin Việt-Pháp (Chương trình ti... | A00, A01, D29 | 27.19 | Math |
| 49 | ME-E1 | Kỹ thuật Cơ điện tử (Chương trình tiên tiến) | A00, A01 | 26.30 | Math |
| 50 | MS-E3 | KHKT Vật liệu (Chương trình tiên tiến) | A00, A01 | 23.99 | Math |
| 51 | TE-E2 | Kỹ thuật Ô tô (Chương trình tiên tiến) | A00, A01 | 26.11 | Math |
| 52 | TE-EP | Cơ khí Hàng không Việt-Pháp (Chương trình tiên... | A00, A01, D29 | 24.76 | Math |
| 53 | ET-LUH | Điện tử Viễn thông-Leibniz Hannover (Đức) | A00, A01, D26 | 25.13 | |
| 54 | ME-GU | Cơ khí Chế tạo máy-Griffith (Úc) | A00, A01 | 23.88 | |
| 55 | ME-LUH | Cơ điện tử-Leibniz Hannover (Đức) | A00, A01, D26 | 25.16 | |
| 56 | ME-NUT | Cơ điện tử-Nagaoka (Nhật Bản) | A00, A01, D28 | 24.88 | |
| 57 | TROY-BA | Quản trị Kinh doanh-Troy (Hoa Kỳ) | A00, A01, D01 | 23.25 | |
| 58 | TROY-IT | Khoa học Máy tính-Troy (Hoa Kỳ) | A00, A01, D01 | 25.50 |
yearS, yearT = 2020, 2021
# Get real grades of target year
data = standard_grades[yearT]
real_grades = {}
for x, y in data.iterrows():
z = list(y.values)
real_grades[z[0]] = z[3]
print(real_grades)
# Add real grades columns to source year table
data = standard_grades[yearS]
new_col = []
for x, y in data.iterrows():
z = list(y)
if z[0] in real_grades:
new_col.append(real_grades[z[0]])
else:
new_col.append(float("NaN"))
standard_grades[yearS][f'Real Grades {yearT}'] = new_col
display(standard_grades[yearS].transpose())
{'BF1': 25.34, 'BF2': 25.94, 'CH1': 25.2, 'CH2': 24.96, 'CH3': 24.45, 'ED2': 24.8, 'EE1': 26.5, 'EE2': 27.46, 'EM1': 25.65, 'EM2': 25.75, 'EM3': 26.04, 'EM4': 25.76, 'EM5': 25.83, 'ET1': 26.8, 'EV1': 24.01, 'EV2': 23.53, 'FL1': 26.39, 'FL2': 26.11, 'HE1': 24.5, 'IT1': 28.43, 'IT2': 28.1, 'ME1': 26.91, 'ME2': 25.78, 'MI1': 27.0, 'MI2': 27.0, 'MS1': 24.65, 'PH1': 25.64, 'PH2': 24.48, 'PH3': 25.36, 'TE1': 26.94, 'TE2': 25.7, 'TE3': 26.48, 'TX1': 23.99, 'BF-E12': 24.44, 'CH-E11': 26.4, 'EE-E18': 25.71, 'EE-E8': 27.26, 'EE-EP': 26.14, 'EM-E13': 25.55, 'EM-E14': 26.33, 'ET-E4': 26.59, 'ET-E5': 25.88, 'ET-E9': 26.93, 'ET-E16': 26.59, 'IT-E6': 27.4, 'IT-E7': 27.85, 'IT-E10': 28.04, 'IT-E15': 27.44, 'IT-EP': 27.19, 'ME-E1': 26.3, 'MS-E3': 23.99, 'TE-E2': 26.11, 'TE-EP': 24.76, 'ET-LUH': 25.13, 'ME-GU': 23.88, 'ME-LUH': 25.16, 'ME-NUT': 24.88, 'TROY-BA': 23.25, 'TROY-IT': 25.5}
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | 56 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Major ID | BF1 | BF2 | BF-E12 | CH1 | CH2 | CH3 | CH-E11 | ED2 | ΕΕ1 | EE2 | ... | PH1 | PH2 | TE1 | TE2 | TE3 | TE-E2 | TE-EP | TROY-BA | TROY-IT | TX1 |
| Major | Kỹ thuật Sinh học | Kỹ thuật Thực phẩm | Kỹ thuật Thực phẩm (CT tiên tiến) | Kỹ thuật Hoá học | Hoá học | Kỹ thuật in | Kỹ thuật Hóa dược (CT tiên tiến) | Công nghệ giáo dục | Kỹ thuật Điện | Kỹ thuật Điều khiển - Tự động hoá | ... | Vật lý kỹ thuật | Kỹ thuật hạt nhân | Kỹ thuật Ô tô | Kỹ thuật Cơ khí động lực | Kỹ thuật Hàng không | Kỹ thuật Ô tô (CT tiên tiến) | Cơ khí hàng không (Chương trình Việt - Pháp PF... | Quản trị kinh doanh - hợp tác với ĐH Troy (Hoa... | Khoa học máy tính - hợp tác với ĐH Troy (Hoa Ký) | Kỹ thuật Dệt - May |
| Subjects Combination | A00, B00, D07 | A00, B00, D07 | A00, B00, D07 | A00, A01, B00, D07 | A00, A01, B00, D07 | A00, A01, B00, D07 | A00, A01, B00, D07 | A00, A01, D01 | A00, A01 | A00, A01 | ... | A00, A01 | A00, A01, A02 | A00, A01 | A00, A01 | A00, A01 | A00, A01 | A00, A01, D29 | A00, A01, D01 | A00, A01, D01 | A00, A01, D07 |
| Standard Grade | 26.2 | 26.6 | 25.94 | 25.26 | 24.16 | 24.51 | 26.5 | 23.8 | 27.01 | 28.16 | ... | 26.18 | 24.7 | 27.33 | 26.46 | 26.94 | 26.75 | 23.88 | 22.5 | 25.0 | 23.04 |
| Main Subject | Math | Math | Math | Math | Math | Math | Math | Math | Math | ... | Math | Math | Math | Math | Math | Math | Math | Math | |||
| Real Grades 2021 | 25.34 | 25.94 | 24.44 | 25.2 | 24.96 | 24.45 | 26.4 | 24.8 | NaN | 27.46 | ... | 25.64 | 24.48 | 26.94 | 25.7 | 26.48 | 26.11 | 24.76 | 23.25 | 25.5 | 23.99 |
6 rows × 57 columns
# Return maximum grade of lowest p% candidates in given subjects combination list
def get_point(percentage, year, subjects_combination):
data = grades[year][subjects_combination].max(1)
data = [round(x,2) for x in data if not np.isnan(x)]
data = sorted(data)
if len(data) == 0: # Return 0 if not valid any candidates
return 0
return data[min(len(data)-1, floor(len(data)*percentage/100))]
# Return percentage range of given point
eps = 0.3 # (point-eps -> point+eps)
def get_percentage(point, year, subjects_combination):
subjects_combination = [x for x in subjects_combination if x in list(grades[year].head())]
data = grades[year][subjects_combination].max(1)
data = [round(x,2) for x in data if not np.isnan(x)]
data = sorted(data)
if len(data) == 0: # Return (0, 0) if not valid any candidates
return 0, 0
return bisect_left(data, point-eps)/len(data)*100, bisect_right(data, point+eps)/len(data)*100
# Exchange point between source year and target year in given subjects combination list
def exchange(point, yearS, yearT, subjects_combination):
subjects_combination = [x for x in subjects_combination if x in list(grades[year].head())]
percentage = get_percentage(point, yearS, subjects_combination)
return get_point(percentage[0], yearT, subjects_combination), get_point(percentage[1], yearT, subjects_combination)
exchange(20, 2018, 2021, ['A00'])
(24.4, 24.8)
# Return list of converted grades from source year to target year
def convert_grades(yearS, yearT):
new_col_1 = []
new_col_2 = []
for x, y in standard_grades[yearS].iterrows():
z = list(y.values)
t = z[2].replace(',', '').split()
if z[4]:
t = [u + '-' + z[4] for u in t]
t = exchange(z[3], yearS, yearT, t)
print(f"[{x+1}\\{len(standard_grades[yearS])}]\t{z[0]}\t{yearS}\t{z[3]}\t{yearT}\t{z[-1]}\t{t}")
new_col_1.append(t[0])
new_col_2.append(t[1])
return new_col_1, new_col_2
results = convert_grades(yearS, yearT)
standard_grades[yearS][f'Predicted Grades Lower {yearT}'] = results[0]
standard_grades[yearS][f'Predicted Grades Upper {yearT}'] = results[1]
[1\57] BF1 2020 26.2 2021 25.34 (25.61, 26.14) [2\57] BF2 2020 26.6 2021 25.94 (25.99, 26.55) [3\57] BF-E12 2020 25.94 2021 24.44 (25.35, 25.91) [4\57] CH1 2020 25.26 2021 25.2 (24.9, 25.46) [5\57] CH2 2020 24.16 2021 24.96 (23.89, 24.45) [6\57] CH3 2020 24.51 2021 24.45 (24.19, 24.75) [7\57] CH-E11 2020 26.5 2021 26.4 (26.06, 26.62) [8\57] ED2 2020 23.8 2021 24.8 (24.25, 24.75) [9\57] ΕΕ1 2020 27.01 2021 nan (26.48, 27.08) [10\57] EE2 2020 28.16 2021 27.46 (27.56, 28.16) [11\57] EE-E8 2020 27.43 2021 27.26 (26.89, 27.49) [12\57] EE-EP 2020 25.68 2021 26.14 (25.2, 25.76) [13\57] EM1 2020 24.65 2021 25.65 (24.95, 25.45) [14\57] EM2 2020 25.05 2021 25.75 (25.25, 25.8) [15\57] EM3 2020 25.75 2021 26.04 (25.85, 26.4) [16\57] EM4 2020 25.3 2021 25.76 (25.45, 26.0) [17\57] EM5 2020 24.6 2021 25.83 (24.9, 25.45) [18\57] EM-E13 2020 25.03 2021 25.55 (24.6, 25.16) [19\57] EM-E14 2020 25.85 2021 26.33 (25.95, 26.45) [20\57] EM-VUW 2020 22.7 2021 nan (23.35, 23.85) [21\57] ET1 2020 27.3 2021 26.8 (26.74, 27.38) [22\57] ET-E4 2020 27.15 2021 26.59 (26.62, 27.22) [23\57] ET-E5 2020 26.5 2021 25.88 (25.99, 26.55) [24\57] ET-E9 2020 27.51 2021 26.93 (26.96, 27.56) [25\57] ET-LUH 2020 23.85 2021 25.13 (23.6, 24.25) [26\57] EV1 2020 23.85 2021 24.01 (23.55, 24.15) [27\57] FL1 2020 24.1 2021 26.39 (25.72, 26.1) [28\57] FL2 2020 24.1 2021 26.11 (25.72, 26.1) [29\57] HE1 2020 25.8 2021 24.5 (25.31, 25.91) [30\57] IT1 2020 29.04 2021 28.43 (28.46, 29.14) [31\57] IT2 2020 28.65 2021 28.1 (28.01, 28.69) [32\57] IT-E10 2020 28.65 2021 28.04 (28.01, 28.69) [33\57] IT-E6 2020 27.98 2021 27.4 (27.41, 28.01) [34\57] IT-E7 2020 28.38 2021 27.85 (27.79, 28.39) [35\57] IT-EP 2020 27.24 2021 27.19 (26.74, 27.3) [36\57] IT-LTU 2020 26.5 2021 nan (26.15, 26.75) [37\57] IT-VUW 2020 25.55 2021 nan (25.25, 25.85) [38\57] ME1 2020 27.48 2021 26.91 (26.92, 27.49) [39\57] ME2 2020 26.51 2021 25.78 (25.99, 26.62) [40\57] ME-E1 2020 26.75 2021 26.3 (26.25, 26.81) [41\57] ME-GU 2020 23.9 2021 23.88 (23.65, 24.3) [42\57] ME-LUH 2020 24.2 2021 25.16 (23.95, 24.6) [43\57] ME-NUT 2020 24.5 2021 24.88 (24.25, 24.9) [44\57] MI1 2020 27.56 2021 27.0 (27.0, 27.6) [45\57] MI2 2020 27.25 2021 27.0 (26.74, 27.3) [46\57] MS1 2020 25.18 2021 24.65 (24.86, 25.42) [47\57] MS-E3 2020 23.18 2021 23.99 (22.95, 23.55) [48\57] PH1 2020 26.18 2021 25.64 (25.65, 26.29) [49\57] PH2 2020 24.7 2021 24.48 (24.26, 24.83) [50\57] TE1 2020 27.33 2021 26.94 (26.78, 27.38) [51\57] TE2 2020 26.46 2021 25.7 (25.95, 26.55) [52\57] TE3 2020 26.94 2021 26.48 (26.44, 27.0) [53\57] TE-E2 2020 26.75 2021 26.11 (26.25, 26.81) [54\57] TE-EP 2020 23.88 2021 24.76 (23.48, 24.07) [55\57] TROY-BA 2020 22.5 2021 23.25 (23.15, 23.7) [56\57] TROY-IT 2020 25.0 2021 25.5 (25.2, 25.75) [57\57] TX1 2020 23.04 2021 23.99 (22.84, 23.44)
# Display prediction
standard_grades[yearS] = standard_grades[yearS].sort_values(['Standard Grade'])
features = [f'Real Grades {yearT}', f'Predicted Grades Lower {yearT}', f'Predicted Grades Upper {yearT}']
data = standard_grades[yearS][['Major ID'] + features].copy()
data = data.dropna()
data = data[data[f'Predicted Grades Lower {yearT}']>=0]
# data = data.sort_values([f'Predicted Grades Lower {yearT}'])
data = data.set_index('Major ID')
rows = []
for x, y in data.iterrows():
for feature in features:
rows.append([x, feature, y[feature]])
data = pd.DataFrame(rows, columns = ["Major ID", "Type", "Grade"])
display(data.transpose())
import plotly.express as px
fig = px.line(data, x='Major ID', y='Grade', color='Type', title="Hanoi University of Science & Technology (HUST) - Standard Passing Grades".upper())
fig.show()
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Major ID | TROY-BA | TROY-BA | TROY-BA | TX1 | TX1 | TX1 | MS-E3 | MS-E3 | MS-E3 | ED2 | ... | IT-E7 | IT-E10 | IT-E10 | IT-E10 | IT2 | IT2 | IT2 | IT1 | IT1 | IT1 |
| Type | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | ... | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 |
| Grade | 23.25 | 23.15 | 23.7 | 23.99 | 22.84 | 23.44 | 23.99 | 22.95 | 23.55 | 24.8 | ... | 28.39 | 28.04 | 28.01 | 28.69 | 28.1 | 28.01 | 28.69 | 28.43 | 28.46 | 29.14 |
3 rows × 159 columns
# Display prediction
standard_grades[yearS] = standard_grades[yearS].sort_values([f'Predicted Grades Lower {yearT}'])
features = [f'Real Grades {yearT}', f'Predicted Grades Lower {yearT}', f'Predicted Grades Upper {yearT}']
data = standard_grades[yearS][['Major ID'] + features].copy()
data = data.dropna()
data = data[data[f'Predicted Grades Lower {yearT}']>=0]
# data = data.sort_values([f'Predicted Grades Lower {yearT}'])
data = data.set_index('Major ID')
rows = []
for x, y in data.iterrows():
for feature in features:
rows.append([x, feature, y[feature]])
data = pd.DataFrame(rows, columns = ["Major ID", "Type", "Grade"])
display(data.transpose())
data.to_csv(f'exchange-grade-{yearS}-{yearT}.csv')
import plotly.express as px
fig = px.line(data, x='Major ID', y='Grade', color='Type', title="Hanoi University of Science & Technology (HUST) - Standard Passing Grades".upper())
fig.show()
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Major ID | TX1 | TX1 | TX1 | MS-E3 | MS-E3 | MS-E3 | TROY-BA | TROY-BA | TROY-BA | TE-EP | ... | IT-E7 | IT-E10 | IT-E10 | IT-E10 | IT2 | IT2 | IT2 | IT1 | IT1 | IT1 |
| Type | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | ... | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 |
| Grade | 23.99 | 22.84 | 23.44 | 23.99 | 22.95 | 23.55 | 23.25 | 23.15 | 23.7 | 24.76 | ... | 28.39 | 28.04 | 28.01 | 28.69 | 28.1 | 28.01 | 28.69 | 28.43 | 28.46 | 29.14 |
3 rows × 159 columns
# Display prediction
standard_grades[yearS] = standard_grades[yearS].sort_values([f'Real Grades {yearT}'])
features = [f'Real Grades {yearT}', f'Predicted Grades Lower {yearT}', f'Predicted Grades Upper {yearT}']
data = standard_grades[yearS][['Major ID'] + features].copy()
data = data.dropna()
data = data[data[f'Predicted Grades Lower {yearT}']>=0]
# data = data.sort_values([f'Predicted Grades Lower {yearT}'])
data = data.set_index('Major ID')
rows = []
for x, y in data.iterrows():
for feature in features:
rows.append([x, feature, y[feature]])
data = pd.DataFrame(rows, columns = ["Major ID", "Type", "Grade"])
display(data.transpose())
import plotly.express as px
fig = px.line(data, x='Major ID', y='Grade', color='Type', title="Hanoi University of Science & Technology (HUST) - Standard Passing Grades".upper())
fig.show()
| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | ... | 149 | 150 | 151 | 152 | 153 | 154 | 155 | 156 | 157 | 158 | |
|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
| Major ID | TROY-BA | TROY-BA | TROY-BA | ME-GU | ME-GU | ME-GU | TX1 | TX1 | TX1 | MS-E3 | ... | IT-E7 | IT-E10 | IT-E10 | IT-E10 | IT2 | IT2 | IT2 | IT1 | IT1 | IT1 |
| Type | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | ... | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 | Real Grades 2021 | Predicted Grades Lower 2021 | Predicted Grades Upper 2021 |
| Grade | 23.25 | 23.15 | 23.7 | 23.88 | 23.65 | 24.3 | 23.99 | 22.84 | 23.44 | 23.99 | ... | 28.39 | 28.04 | 28.01 | 28.69 | 28.1 | 28.01 | 28.69 | 28.43 | 28.46 | 29.14 |
3 rows × 159 columns